<?php

namespace Plugin\PaypalSiteB\Services;


use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Matrix\Exception;
use Plugin\PaypalSiteB\Models\PollingPaymentIndex;
use Plugin\PaypalSiteB\Models\PollingPaymentOrders;
use Srmklive\PayPal\Services\PayPal;

class PollingPaypalTools
{
    //根据onrderNo获取当前应该使用哪个配置
    public function getPollingSetting($orderNo, $payment_code = 'paypal_site_b')
    {
        $allSettings = plugin_setting($payment_code . '.setting', []);
        if (empty($allSettings)) {
            return null;
        }
        $allSettings = $allSettings['polling_paypal'];

        DB::beginTransaction();
        $settings            = null;
        $pollingPaymentOrder = PollingPaymentOrders::query()->where("order_no", $orderNo)->where("payment_code", $payment_code)->first();
        if ($pollingPaymentOrder) {//已经初始化过该订单，检查当前帐户是否还是正常的
            $settings = json_decode($pollingPaymentOrder->payment_config, true);

            $noSetting = true;
            foreach ($allSettings as $key => $setting) {
                if ($settings['key'] == $settings['key']) {
                    $noSetting = false;
                    if ($setting['status'] == 0) {//关闭了
                        PollingPaymentOrders::query()->where("order_no", $orderNo)->where("payment_code", $payment_code)->delete();
                        $pollingPaymentOrder = null;
                    }
                }
            }
            if ($noSetting) {
                PollingPaymentOrders::query()->where("order_no", $orderNo)->where("payment_code", $payment_code)->delete();
                $pollingPaymentOrder = null;
                $settings            = null;
            }
        }

        if ($pollingPaymentOrder) {//已经初始化过该订单
            $settings = json_decode($pollingPaymentOrder->payment_config, true);
            DB::commit();
        } else {
            $settings = null;
            try {
                $usedWeight = false;
                $tmpWeight  = null;
                $weights    = [];
                foreach ($allSettings as $key => $setting) {
                    if ($setting['status'] == 1) {
                        $weights[$key] = $setting['weight'];
                        if ($tmpWeight == null) {
                            $tmpWeight = $setting['weight'];
                        } else if ($tmpWeight != $setting['weight']) {//存在不一样的权重值，说明是按权重了
                            $usedWeight = true;
                        }
                    }
                }
                $ppIndex = null;
                $index   = null;
                if ($usedWeight) {
                    $index = $this->weightedRandom($weights);
                    $index = $index - 1;
                } else {
                    $ppIndex = PollingPaymentIndex::query()->where("payment_code", $payment_code)->first();
                    if ($ppIndex) {
                        $index = $ppIndex->now_index + 1;
                    }
                }
                if ($index != null) {
                    foreach ($allSettings as $key => $setting) {
                        if ($key >= $index && $setting['status'] == 1) {
                            $settings = $setting;
                            break;
                        }
                    }
                    if ($settings == null) {
                        foreach ($allSettings as $key => $setting) {
                            if ($setting['status'] == 1) {
                                $settings = $setting;
                                $index    = $key;
                                break;
                            }
                        }
                    }
                    if ($settings == null) {
                        DB::rollBack();
                        return null;
                    }
                    if (!$usedWeight) {
                        $ppIndex->now_index  = $index;
                        $ppIndex->updated_at = Carbon::now()->toDateTimeString();
                        $ppIndex->update();
                    }
                    //取出配置数据
                } else {
                    foreach ($allSettings as $key => $setting) {
                        if ($setting['status'] == 1) {
                            $settings = $setting;
                            $index    = $key;
                            break;
                        }
                    }
                    if ($settings == null) {
                        DB::rollBack();
                        return null;
                    }
                    if (!$usedWeight) {
                        $indeData = [
                            'payment_code' => $payment_code,
                            'now_index'    => $index,
                            'created_at'   => Carbon::now()->toDateTimeString(),
                            'updated_at'   => Carbon::now()->toDateTimeString()
                        ];
                        DB::table('polling_payment_index')->insertGetId($indeData);
                    }
                }


                $pData = [
                    'payment_code'   => $payment_code,
                    'order_no'       => $orderNo,
                    'payment_config' => json_encode($settings),
                    'created_at'     => Carbon::now()->toDateTimeString(),
                    'updated_at'     => Carbon::now()->toDateTimeString()
                ];
                DB::table('polling_payment_orders')->insertGetId($pData);

                DB::commit();
            } catch (\Exception $exception) {
                DB::rollBack();
            }
        }
        return $settings;
    }

    /**
     * 根据权重占比的随机函数
     *
     * @param array $weights 权重数组，键为选项，值为该选项的权重
     * @return string|int 返回被选中的键（选项）
     */
    private function weightedRandom(array $weights)
    {
        // 计算权重总和
        $totalWeight = array_sum($weights);

        if ($totalWeight <= 0) {
            throw new Exception("权重总和必须大于0");
        }

        // 生成一个 [0, 总权重) 范围内的随机数
        $random = mt_rand(1, $totalWeight);

        // 遍历权重数组，找到随机数对应的选项

        foreach ($weights as $key => $weight) {
            $random -= $weight;
            if ($random <= 0) {
                return $key;
            }
        }

        // 理论上不会到达这里
        throw new Exception("随机选择失败，请检查权重数组");
    }

    public function pushToASite($order_no, $status)
    {
        $allSettings = plugin_setting('useepay_site_b' . '.setting', []);
        if (empty($allSettings)) {
            return null;
        }
        $token       = $allSettings["token"];
        $data_string = ['status' => $status];



        $this->httpPost($token, $domain, "/callback/paypal_site_a/capture?order_no=" . $order_no, $data_string);
    }

    public function httpPost($token, $domain, $method, $data_string)
    {

        //对数据加密
        $time     = time();
        $key      = md5($time . $token . $time);
        $aesTools = new AesTools($key);
        $data     = $aesTools->encrypt($data_string);
        $postData = [
            'time' => $time,
            'data' => $data
        ];
        $postData = json_encode($postData, true);
        $headers  = [
            "Content-Type: application/json; charset=utf-8",
            "Content-Length: " . strlen($postData),
        ];

        Log::debug($postData);
        $ci = curl_init();
        curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
        curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ci, CURLOPT_ENCODING, "");
        curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ci, CURLOPT_HEADER, FALSE);
        curl_setopt($ci, CURLOPT_POST, TRUE);
        curl_setopt($ci, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ci, CURLOPT_URL, $domain . $method);
        curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ci, CURLINFO_HEADER_OUT, TRUE);
        curl_setopt($ci, CURLOPT_USERAGENT, request()->userAgent()); // 设置UserAgent

        $response = curl_exec($ci);
        curl_close($ci);

        return $response;
    }

    private function getHost($settings)
    {
        if ($settings['is_debug']) {
            return 'https://api-m.sandbox.paypal.com';
        } else {
            return "https://api-m.paypal.com";
        }
    }

    /**
     * 获取 PayPal 的 Access Token
     *
     * @return string Access Token
     */
    private function getAccessToken($settings)
    {


        $url = $this->getHost($settings) . "/v1/oauth2/token";

        $headers = [
            "Accept: application/json",
            "Accept-Language: en_US",
        ];

        $data = "grant_type=client_credentials";

        Log::debug($settings['key'] . ":" . $settings['secret']);
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_USERPWD, $settings['key'] . ":" . $settings['secret']);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $response   = curl_exec($ch);
        $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        curl_close($ch);

        if ($httpStatus !== 200) {
            throw new Exception("上传物流单号失败(2):" . "Error fetching Access Token: " . $response);
        }

        $response = json_decode($response, true);
        return $response['access_token'];
    }

    /**
     * 使用 PayPal Tracking API 上传物流信息
     *
     * @param string $transactionId  PayPal 交易 ID
     * @param string $trackingNumber 物流单号
     * @param string $carrierName    承运商名称（如 UPS、FedEx 等）
     * @param string $status         物流状态（如 SHIPPED, IN_TRANSIT, DELIVERED 等）
     * @param bool   $notifyBuyer    是否通知买家
     */
    public function uploadExpressInfo($order, $transactionId, $trackingNumber, $carrierName, $notifyBuyer = true)
    {
        $payment_code        = "paypal_site_b";
        $pollingPaymentOrder = PollingPaymentOrders::query()->where("order_no", $order->number)->where("payment_code", $payment_code)->first();
        if (!$pollingPaymentOrder) {//已经初始化过该订单，检查当前帐户是否还是正常的
            Log::debug("pollingPaymentOrder is null");
            return true;
        }
        if (empty($pollingPaymentOrder->gateway_order_id)) {//已经初始化过该订单，检查当前帐户是否还是正常的
            Log::debug("gateway_order_id is null");
            return true;
        }
        $settings = json_decode($pollingPaymentOrder->payment_config, true);
        //$accessToken = $this->getAccessToken($settings);


        $config             = [
            'mode'           => $settings['is_debug'] == 1 ? 'sandbox' : 'live',
            'sandbox'        => [
                'client_id'     => $settings['key'],
                'client_secret' => $settings['secret'],
            ],
            'live'           => [
                'client_id'     => $settings['key'],
                'client_secret' => $settings['secret'],
            ],
            'payment_action' => 'Sale',
            'currency'       => $order->currency_code,
            'notify_url'     => '',
            'locale'         => 'en_US',
            'validate_ssl'   => false,
        ];
        $this->paypalClient = new PayPal($config);
        $index              = 0;
        $accessToken        = null;
        while ($index < 3) {
            $index++;
            try {
                $accessToken = $this->paypalClient->getAccessToken();
                break;
            } catch (\ErrorException $exception) {
                $token = null;
            }
        }
        if (!$accessToken) {
            throw new Exception("上传物流单号失败(2):" . "获取token失败");
        }
        $url = $this->getHost($settings) . "/v1/shipping/trackers-batch";

        // 构建请求数据
        $data = [
            "trackers" => [
                [
                    "transaction_id"  => $transactionId,
                    "tracking_number" => $trackingNumber,
                    "status"          => 'SHIPPED',
                    // 如：SHIPPED, IN_TRANSIT, DELIVERED
                    "carrier"         => $carrierName,
                    // 如 UPS, FedEx, DHL
                    "notify_buyer"    => $notifyBuyer
                    // 是否通知买家
                ]
            ]
        ];

        $headers = [
            "Content-Type: application/json",
            "Authorization: Bearer " . $accessToken['access_token'],
        ];

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $response   = curl_exec($ch);
        $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        curl_close($ch);


        // 检查响应状态
        if ($httpStatus !== 200) {
            //die("Error uploading tracking info: " . $response);
            Log::debug($pollingPaymentOrder->gateway_order_id . "Error uploading tracking info: " . $response);
            return false;
        }

        Log::debug($pollingPaymentOrder->gateway_order_id . "Tracking info uploaded successfully!");
        //$response = json_decode($response, true);
        return true;
        //echo "Tracking info uploaded successfully! Response: " . print_r($response, true);
    }
}
